/*抽象工厂模式*/

#include <iostream>
#include <memory>
using namespace std;


// ver 3
class Fruit
{
public:
    virtual void name() = 0;
};

class Apple : public Fruit
{
public:
    void name() override
    {
        cout << "i am apple" << endl;
    }
};

class Banana : public Fruit
{
public:
    void name() override
    {
        cout << "i am Banana" << endl;
    }
};


class Animal
{
public:
    virtual void name() = 0;
};

class Dog : public Animal
{
public:
    void name() override
    {
        cout << "i am a dog" << endl;
    }
};

class Cat : public Animal
{
public:
    void name() override
    {
        cout << "i am a Cat" << endl;
    }
};

class Factory
{
public:
    virtual shared_ptr<Fruit> GetFruit(const string &name) = 0;
    virtual shared_ptr<Animal> GetAnimal(const string &name) = 0;
};

class FruitFactory : public Factory
{
public:
    shared_ptr<Animal> GetAnimal(const string &name)
    {
        return shared_ptr<Animal>();
    }

    shared_ptr<Fruit> GetFruit(const string &name)
    {
        if (name == "apple")
        {
            return make_shared<Apple>();
        }
        else if (name == "banana")
        {
            return make_shared<Banana>();
        }
    }
};

class AnimalFactory : public Factory
{
public:
    shared_ptr<Animal> GetAnimal(const string &name)
    {
        if (name == "dog")
        {
            return make_shared<Dog>();
        }
        else if (name == "cat")
        {
            return make_shared<Cat>();
        }
    }

    shared_ptr<Fruit> GetFruit(const string &name)
    {
        return shared_ptr<Fruit>();
    }
};

class FactoryProducer
{
public:
    static shared_ptr<Factory> create(const string &name)
    {
        if (name == "fruit")
        {
            return make_shared<FruitFactory>();
        }
        else if (name == "animal")
        {
            return make_shared<AnimalFactory>();
        }
    }
};

int main()
{
    shared_ptr<Factory> ff = FactoryProducer::create("fruit");
    shared_ptr<Fruit> fruit = ff->GetFruit("apple");
    fruit->name();

    ff = FactoryProducer::create("animal");
    shared_ptr<Animal> animal = ff->GetAnimal("cat");
    animal->name();

    return 0;
}

//////////////////////////////////////////////////////////////////////
// ver 2 ver 1


// class Fruit
// {
// public:
//     virtual void name() = 0;
// };

// class Apple : public Fruit
// {
// public:
//     void name() override
//     {
//         cout << "i am apple" << endl;
//     }
// };

// class Banana : public Fruit
// {
// public:
//     void name() override
//     {
//         cout << "i am Banana" << endl;
//     }
// };



// class FruitFactory
// {
// public:
//     // version 2 遵循开闭原则
//     virtual shared_ptr<Fruit> create() = 0;

//     // version 1 违背了开闭原则
//     // static shared_ptr<Fruit> create(const string& name)
//     // {
//     //     if(name == "apple")
//     //     {
//     //         return make_shared<Apple>();
//     //     }
//     //     else if(name == "banana")
//     //     {
//     //         return make_shared<Banana>();
//     //     }
//     // }
// };

// class AppleFactory : public FruitFactory
// {
// public:
//     shared_ptr<Fruit> create() override
//     {
//         return make_shared<Apple>();
//     }
// };

// class BananaFactory : public FruitFactory
// {
// public:
//     shared_ptr<Fruit> create() override
//     {
//         return make_shared<Banana>();
//     }
// };

// int main()
// {
//     // 直接new对象后，以后如果对象的构造方法发生改变
//     // 那就要修改很多地方，所以交给工厂去处理

//     // ver 3 抽象工厂

//     // ver 2 工厂分类
//     // shared_ptr<FruitFactory> ff(new AppleFactory());
//     // shared_ptr<Fruit> fruit = ff->create();
//     // fruit->name();

//     // ff.reset(new BananaFactory());
//     // fruit = ff->create();
//     // fruit->name();

//     // ver 1 简单工厂
//     // shared_ptr<Fruit> fruit = FruitFactory::create("apple");
//     // fruit->name();
//     // fruit = FruitFactory::create("banana");
//     // fruit->name();

//     return 0;
// }